package academic.concordia.bankofquebec.bean.bankAccount;

import java.util.ArrayList;
import java.util.List;

import org.springframework.transaction.annotation.Transactional;

import academic.concordia.bankofquebec.dao.client.IClientDAO;
import academic.concordia.bankofquebec.dao.bankaccount.IBankAccountDAO;
import academic.concordia.bankofquebec.entity.AccountAttributes;
import academic.concordia.bankofquebec.entity.BankAccount;
import academic.concordia.bankofquebec.entity.Client;
import academic.concordia.bankofquebec.entity.Transaction;
import academic.concordia.bankofquebec.entity.TransactionStatus;

@Transactional(readOnly = true)
public class BankAccountServices implements IBankAccountServices {
	
	IClientDAO clientDAO;
	
	IBankAccountDAO bankAccountDAO;

	@Transactional(readOnly = false)
	@Override
	public synchronized Transaction transfer(BankAccount fromAccount, BankAccount toAccount,
			double amount) {
		
		Transaction withdrawal = fromAccount.withdraw(amount);
		if (withdrawal.isApproved()){
			Transaction deposit = toAccount.deposit(amount);
			deposit.setAuthorizationNumber(withdrawal.getAuthorizationNumber());
			
			bankAccountDAO.updateBankAccount(fromAccount);
			bankAccountDAO.updateBankAccount(toAccount);
		}
		return withdrawal;
	}

	@Override
	public Transaction withdrawal(BankAccount account, double amount) {
		Transaction withdrawal = account.withdraw(amount);
		if (withdrawal.isApproved())
			bankAccountDAO.updateBankAccount(account);
		return withdrawal;
	}

	@Override
	public Transaction deposit(BankAccount account, double amount) {
		Transaction deposit = account.deposit(amount);
		bankAccountDAO.updateBankAccount(account);
		return deposit;
	}

	@Override
	public List<BankAccount> getTransferAccounts(Client client) {
		List<BankAccount> products = client.getProducts();
		List<BankAccount> transferAccounts = new ArrayList<BankAccount>();
		for (int i=0; i<products.size(); i++){
			if (products.get(i).isTransferAccount()){
				transferAccounts.add(products.get(i));
			}
		}
		return transferAccounts;
	}

	@Override
	public List<BankAccount> getOtherTransferAccounts(Client client, BankAccount currentAccount) {
		List<BankAccount> products = getTransferAccounts(client);
		List<BankAccount> transferAccounts = new ArrayList<BankAccount>();
		if (!currentAccount.getType().equals(AccountAttributes.CHECKINGS_ACCOUNT.name())){
			transferAccounts.add(client.getProduct(AccountAttributes.CHECKINGS_ACCOUNT.name()));
			return transferAccounts;
		}
		else {
			for (BankAccount product : products){
				if (!product.getType().equals(AccountAttributes.CHECKINGS_ACCOUNT.name())){
					transferAccounts.add(product);
				}
			}
			return transferAccounts;
		}
	}

	@Override
	public List<Transaction> getMonthlyStatement() {
		// TODO Auto-generated method stub
		return null;
	}

	@Transactional(readOnly = false)
	@Override
	public boolean addAccount(BankAccount newAccount, Client client) {
		if (client.hasProduct(newAccount.getType()))
			return false; 
		
		newAccount.setHolder(client);
		newAccount.createBankAccountNumber();
		client.addProduct(newAccount);
		// actualizar el cliente
		clientDAO.updateClient(client);
		return true;
	}

	public IClientDAO getClientDAO() {
		return clientDAO;
	}

	public void setClientDAO(IClientDAO clientDAO) {
		this.clientDAO = clientDAO;
	}
	
	@Override
	public BankAccount getAccountById(String id) {
		return bankAccountDAO.getAccountById(id);
	}

	public IBankAccountDAO getBankAccountDAO() {
		return bankAccountDAO;
	}

	public void setBankAccountDAO(IBankAccountDAO bankAccountDAO) {
		this.bankAccountDAO = bankAccountDAO;
	}
	
	//public List<Transaction> getAccountTransactions
	
}
